{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Melanoma_detection_db_rank2.ipynb",
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "code",
      "metadata": {
        "id": "4CL2i3yPf0wF",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#PLEASE CHANGE RUNTIME TO GPU IN COLLAB\n",
        "#THE BELOW WORK IS A RESULT OF COLLABORATION AND IDEA EXCHANGE BETWEEN SAI, SAYANTAN AND MYSELF. THEY DESERVE THIS RANK AS MUCH AS I.\n",
        "##YOU NEED TO CHANGE ADDRESS TO SAVE IN 4 PLACES INSIDE THIS CODE, PLEASE FOLLOW COMMENTS\n",
        "!pip install catboost\n",
        "!pip install --upgrade pandas\n",
        "!pip install --upgrade numpy\n",
        "!pip install -U scikit-learn==0.21\n",
        "!pip install scikit-optimize"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "FXe8Lj4vkLwZ",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 122
        },
        "outputId": "a6709ec9-7adf-4003-9117-0fb16dc0da72"
      },
      "source": [
        "import numpy as np\n",
        "import pandas as pd\n",
        "from IPython.display import clear_output\n",
        "import matplotlib.pyplot as plt\n",
        "%matplotlib inline\n",
        "# from reg_resampler import resampler\n",
        "from sklearn.feature_selection import SelectFromModel\n",
        "from sklearn.model_selection import KFold, cross_val_score\n",
        "from sklearn.model_selection import cross_validate,cross_val_score\n",
        "import seaborn as sns\n",
        "from sklearn.metrics import mean_squared_error ,accuracy_score\n",
        "from google.colab import files\n",
        "from sklearn.model_selection import KFold, train_test_split\n",
        "import csv\n",
        "import numpy as np\n",
        "import os\n",
        "import featuretools as ft\n",
        "import featuretools.variable_types as vtypes\n",
        "from catboost import CatBoostRegressor\n",
        "import warnings\n",
        "from math import sqrt\n",
        "from sklearn.ensemble import ExtraTreesRegressor\n",
        "from google.colab import drive\n",
        "import sklearn as sk\n",
        "from scipy import stats\n",
        "import re\n",
        "from collections import Counter\n",
        "import matplotlib.pyplot as plt\n",
        "import warnings\n",
        "warnings.filterwarnings('ignore')\n",
        "drive.mount(\"/GD\")"
      ],
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/statsmodels/tools/_testing.py:19: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.\n",
            "  import pandas.util.testing as tm\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            "Drive already mounted at /GD; to attempt to forcibly remount, call drive.mount(\"/GD\", force_remount=True).\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/sklearn/externals/joblib/__init__.py:15: DeprecationWarning: sklearn.externals.joblib is deprecated in 0.21 and will be removed in 0.23. Please import this functionality directly from joblib, which can be installed with: pip install joblib. If this warning is raised when loading pickled models, you may need to re-serialize those models with scikit-learn 0.21+.\n",
            "  warnings.warn(msg, category=DeprecationWarning)\n"
          ],
          "name": "stderr"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "YGms43hVmZ-W",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def reduce_mem_usage(df, verbose=True):\n",
        "    numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']\n",
        "    #objecttype=['object']\n",
        "    start_mem = df.memory_usage().sum() / 1024**2    \n",
        "    for col in df.columns:\n",
        "        col_type = df[col].dtypes\n",
        "        if col_type in numerics:\n",
        "            c_min = df[col].min()\n",
        "            c_max = df[col].max()\n",
        "            if str(col_type)[:3] == 'int':\n",
        "                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:\n",
        "                    df[col] = df[col].astype(np.int8)\n",
        "                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:\n",
        "                    df[col] = df[col].astype(np.int16)\n",
        "                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:\n",
        "                    df[col] = df[col].astype(np.int32)\n",
        "                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:\n",
        "                    df[col] = df[col].astype(np.int64)  \n",
        "            else:\n",
        "                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:\n",
        "                    df[col] = df[col].astype(np.float16)\n",
        "                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:\n",
        "                    df[col] = df[col].astype(np.float32)\n",
        "                else:\n",
        "                    df[col] = df[col].astype(np.float64)\n",
        "        #if col_type in objecttype:\n",
        "            #df[col]=df[col].astype('category')\n",
        "    end_mem = df.memory_usage().sum() / 1024**2\n",
        "    if verbose: print('Mem. usage decreased to {:5.2f} Mb ({:.1f}% reduction)'.format(end_mem, 100 * (start_mem - end_mem) / start_mem))\n",
        "    return df"
      ],
      "execution_count": 2,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "nyrowfmbmlX5",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#PREPROCESSING MODULE\n",
        "#######change address here for verification#############\n",
        "df_train = pd.read_csv(\"/GD/My Drive/cancer/Train.csv\")\n",
        "df_test = pd.read_csv(\"/GD/My Drive/cancer/Test.csv\")\n",
        "########################################################\n",
        "key=df_train.drop(['tumor_size'],axis=1).columns.tolist()\n",
        "df_test['key']=df_test[key].apply(lambda x: '_'.join(x.astype('str')), axis = 1)\n",
        "df_train['key']=df_train[key].apply(lambda x: '_'.join(x.astype('str')), axis = 1)\n",
        "df=pd.DataFrame(df_train.groupby(['key'],as_index=False)['tumor_size'].mean())\n",
        "df=df.reset_index()\n",
        "encode = dict(zip(df.key, df.tumor_size))\n",
        "df_test['tumor_size']=df_test.key.map(encode)\n",
        "df_test2=df_test[np.isnan(df_test.tumor_size)].drop(['tumor_size'],axis=1)\n",
        "df_train2=df_train.drop(['tumor_size'],axis=1).drop_duplicates()\n",
        "encode3 = dict(zip(df_train.key, df_train.tumor_size))\n",
        "df_train2['tumor_size']=df_train2.key.map(encode3)\n",
        "df_train2=df_train2[df_train2.tumor_size>0]\n",
        "df_test2['is_what']='test'\n",
        "df_train2['is_what']='train'\n",
        "Y=df_train2['tumor_size']\n",
        "fulldf=df_train2.drop(['tumor_size'],axis=1).append(df_test2)\n",
        "reduce_mem_usage(fulldf)\n"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "wwEB-YWwne0c",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#################################FEATURE ENGINEERING#######################################################################\n",
        "df2=fulldf\n",
        "es = ft.EntitySet(id = 'power')\n",
        "categories=['key','is_what']\n",
        "variable_types=dict.fromkeys(categories, vtypes.Categorical)\n",
        "\n",
        "es.entity_from_dataframe(entity_id = 'data', dataframe = df2, \n",
        "                         make_index = True, index = 'index',variable_types=variable_types)\n",
        "feature_matrix, feature_list = ft.dfs(entityset = es, target_entity = 'data',\n",
        "                                      trans_primitives = ['percentile','divide','multiply'],max_depth=2\n",
        "                                      )\n",
        "main2=feature_matrix\n",
        "main2.replace([np.inf, -np.inf], np.nan,inplace=True)\n",
        "TEST=main2[main2['is_what']=='test'].drop(['is_what'],axis=1)\n",
        "TRAIN=main2[main2['is_what']=='train'].drop(['is_what'],axis=1)\n",
        "#NOW COMBINING SAYANTAN AND SAI'S FEATURES\n",
        "#sayantan's features\n",
        "TRAIN['total_estimated_samples'] =   TRAIN['err_malign'] / TRAIN['std_dev_malign']  \n",
        "TEST['total_estimated_samples'] =   TEST['err_malign'] / TEST['std_dev_malign'] \n",
        "TRAIN['tumor_area'] = TRAIN['exposed_area'] - TRAIN['damage_size']\n",
        "TEST['tumor_area'] = TEST['exposed_area'] - TEST['damage_size']\n",
        "TRAIN['tumor_mass'] = TRAIN['tumor_area'] * TRAIN['mass_npea'] / TRAIN['size_npear']\n",
        "TEST['tumor_mass'] = TEST['tumor_area'] * TEST['mass_npea'] / TEST['size_npear']\n",
        "TRAIN['feat_1'] = TRAIN['malign_penalty'] * TRAIN['mass_npea']\n",
        "TEST['feat_1'] = TEST['malign_penalty'] * TEST['mass_npea']\n",
        "\n",
        "#sai's features\n",
        "TRAIN[\"exposed_area_by_size_npear\"] = (TRAIN[\"exposed_area\"]/TRAIN[\"size_npear\"])*TRAIN[\"malign_ratio\"]\n",
        "TEST[\"exposed_area_by_size_npear\"] = (TEST[\"exposed_area\"]/TEST[\"size_npear\"])*TEST[\"malign_ratio\"]\n"
      ],
      "execution_count": 18,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "rBtflSU6q6f_",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 85
        },
        "outputId": "6381f4c4-d23e-4636-d32b-37e723258a07"
      },
      "source": [
        "###CHANGE THE ADDRESS BELOW BEFORE RUNNING THIS CODE. REPLACE ADDRESS 1 WITH UR LOCATION########\n",
        "#feature selection, the biggest headache and the most time wasted doing this\n",
        "CBOTHER=['total_estimated_samples', 'err_malign', 'damage_size', 'damage_ratio',\n",
        "       'tumor_mass', 'exposed_area_by_size_npear', 'malign_penalty', 'feat_1',\n",
        "       'std_dev_malign', 'tumor_area']\n",
        "MAINCB=['size_npear / damage_size', 'PERCENTILE(damage_size) / damage_size',\n",
        "       'exposed_area_by_size_npear',\n",
        "       'PERCENTILE(mass_npea) / PERCENTILE(exposed_area)',\n",
        "       'malign_penalty / damage_size', 'PERCENTILE(exposed_area) / size_npear',\n",
        "       'damage_ratio * err_malign',\n",
        "       'malign_penalty / err_malign * malign_ratio / damage_size',\n",
        "       'damage_size / size_npear',\n",
        "       'malign_penalty / damage_size * malign_ratio / damage_size',\n",
        "       'malign_ratio / exposed_area * PERCENTILE(err_malign)',\n",
        "       'malign_penalty / PERCENTILE(malign_penalty)',\n",
        "       'damage_ratio / exposed_area * damage_size / malign_ratio',\n",
        "       'PERCENTILE(malign_penalty) / damage_size',\n",
        "       'malign_penalty / mass_npea * PERCENTILE(damage_ratio)',\n",
        "       'err_malign / mass_npea * PERCENTILE(std_dev_malign)',\n",
        "       'err_malign / damage_size * PERCENTILE(damage_ratio)',\n",
        "       'damage_ratio * PERCENTILE(std_dev_malign)',\n",
        "       'PERCENTILE(mass_npea) / PERCENTILE(malign_penalty)',\n",
        "       'malign_ratio / err_malign * PERCENTILE(malign_penalty)',\n",
        "       'PERCENTILE(std_dev_malign) / mass_npea',\n",
        "       'malign_penalty / std_dev_malign * malign_ratio / exposed_area',\n",
        "       'damage_size / mass_npea * std_dev_malign / mass_npea',\n",
        "       'PERCENTILE(damage_ratio) * PERCENTILE(err_malign)',\n",
        "       'PERCENTILE(err_malign) / PERCENTILE(exposed_area)',\n",
        "       'damage_ratio * PERCENTILE(err_malign)',\n",
        "       'damage_ratio / damage_size * malign_penalty / damage_size',\n",
        "       'PERCENTILE(err_malign) / std_dev_malign',\n",
        "       'damage_ratio / std_dev_malign * damage_size',\n",
        "       'PERCENTILE(malign_penalty) / malign_ratio',\n",
        "       'PERCENTILE(std_dev_malign) / err_malign',\n",
        "       'damage_ratio * PERCENTILE(damage_size)',\n",
        "       'err_malign / std_dev_malign * malign_ratio / mass_npea',\n",
        "       'PERCENTILE(malign_penalty) / err_malign',\n",
        "       'malign_penalty / size_npear * PERCENTILE(damage_ratio)',\n",
        "       'err_malign / size_npear * malign_ratio / damage_ratio',\n",
        "       'err_malign / damage_size * malign_penalty / damage_size']\n",
        "imp_columns=CBOTHER+MAINCB\n",
        "IMP_COLUMNS2=list(set(imp_columns))\n",
        "TRAIN_FINAL=TRAIN[IMP_COLUMNS2]\n",
        "TEST_FINAL=TEST[IMP_COLUMNS2]\n",
        "reduce_mem_usage(TRAIN_FINAL)\n",
        "reduce_mem_usage(TEST_FINAL)\n",
        "#BELOW PART FREES UP RAM AND MAKES IT SUSTAINABLE TO RUN THE UPCOMING MODELS\n",
        "#####change address here#############\n",
        "#DONT CHANGE THE SAVING FILE NAME JUST CHANGE THE LOCATION AS PER YOUR OWN DRIVE\n",
        "TRAIN_FINAL.to_csv(\"/GD/My Drive/cancer/TRAIN_FINAL.csv\",index=False)\n",
        "TEST_FINAL.to_csv(\"/GD/My Drive/cancer/TEST_FINAL.csv\",index=False)\n",
        "Y.to_csv(\"/GD/My Drive/cancer/Y.csv\",index=False)\n",
        "########################################\n",
        "\n",
        "#CB COMPLETELY TUNED AND PROVIDED BY SAI.\n",
        "cb1=CatBoostRegressor(random_state=25,n_estimators=4000,task_type=\"GPU\",devices=\"0:1\",boosting_type=\"Plain\",#.6\n",
        "                              verbose=0,max_depth=13,learning_rate=0.09)\n",
        "cb2=CatBoostRegressor(random_state=18,n_estimators=3000,task_type=\"GPU\",devices=\"0:1\",boosting_type=\"Plain\",#.4\n",
        "                              verbose=0,max_depth=11,learning_rate=0.095)\n",
        "\n",
        "\n",
        "###CHANGE ADDRESS HERE GIVE SAME LOCATION AS ABOVE IN PLACE OF ADDRESS 1###########\n",
        "###THIS PART NEEDED TO FREE UP RUNTIME MEMORY#################\n",
        "TRAIN_FINAL=pd.read_csv(\"/GD/My Drive/cancer/TRAIN_FINAL.csv\")\n",
        "TEST_FINAL=pd.read_csv(\"/GD/My Drive/cancer/TEST_FINAL.csv\")\n",
        "Y=pd.read_csv(\"/GD/My Drive/cancer/Y.csv\")\n",
        "Y=Y['tumor_size']\n",
        "##################################\n",
        "reduce_mem_usage(TRAIN_FINAL)\n",
        "reduce_mem_usage(TEST_FINAL)\n",
        "TRAIN=[]\n",
        "TEST=[]"
      ],
      "execution_count": 19,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Mem. usage decreased to  0.94 Mb (66.5% reduction)\n",
            "Mem. usage decreased to  3.77 Mb (66.5% reduction)\n",
            "Mem. usage decreased to  0.88 Mb (72.3% reduction)\n",
            "Mem. usage decreased to  3.50 Mb (72.3% reduction)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "LOLYCqWVtbZV",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 289
        },
        "outputId": "c57c331e-240e-4553-88a8-753f76712f17"
      },
      "source": [
        "#Runtime 55mins\n",
        "#FOR CB1 warning: takes huge time! if you are happy with a little lesser scores, reduce the estimators!\n",
        "#suggest to open another google collab window and run two folds simultaneously. You can combine them by ratios even manually later from excel\n",
        "i=0\n",
        "l=[]\n",
        "setused=TRAIN_FINAL[MAINCB]\n",
        "targ=Y\n",
        "test=TEST_FINAL\n",
        "scores=[]\n",
        "splits=15\n",
        "cnf_matrix=[]\n",
        "oof_preds = np.zeros((len(test)))\n",
        "kfold, scores = KFold(n_splits=splits,random_state=True), list()\n",
        "for train2, test2 in kfold.split(setused,targ):\n",
        "    x_train, x_test = setused.values[train2], setused.values[test2]\n",
        "    y_train, y_test = targ.values[train2], targ.values[test2]\n",
        "    model = cb1\n",
        "    model.fit(x_train, y_train)\n",
        "    preds = model.predict(x_test)\n",
        "    #############################\n",
        "    feature_importances = pd.DataFrame(model.feature_importances_,\n",
        "                                       index = setused.columns,\n",
        "                                        columns=['importance'])\n",
        "    sum=feature_importances.values\n",
        "    l.append(sum)\n",
        "    #############################\n",
        "    score = np.sqrt(mean_squared_error(y_test, preds))\n",
        "    scores.append(score)\n",
        "    print(score)\n",
        "    oof_preds += model.predict(test[setused.columns.tolist()].values)\n",
        "oof_preds = oof_preds/splits\n",
        "\n",
        "print(\"Average: \", np.sum(scores)/len(scores))\n",
        "#3.395748867305454"
      ],
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "3.395748867305454\n",
            "3.635446459349284\n",
            "3.4622486979800278\n",
            "3.4417551028858937\n",
            "3.5530359422377304\n",
            "3.5215868209170895\n",
            "3.5882127096584573\n",
            "3.7874274457968276\n",
            "3.8404595386530884\n",
            "3.8220729898474155\n",
            "3.5969254205796566\n",
            "3.5674265119946464\n",
            "3.7747989575715395\n",
            "3.303760235792461\n",
            "3.719877148303528\n",
            "Average:  3.6007188565915396\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "w2USbTclJff6",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 306
        },
        "outputId": "d7fbd994-c72e-44c5-cb82-07006012cf55"
      },
      "source": [
        "#for CB2. RUNTIME AT 15MINS\n",
        "#suggest to open another google collab window and run two folds simultaneously. You can combine them by ratios even manually later from excel\n",
        "i=0\n",
        "l=[]\n",
        "setused=TRAIN_FINAL[CBOTHER]\n",
        "targ=Y\n",
        "test=TEST_FINAL\n",
        "scores=[]\n",
        "splits=16\n",
        "cnf_matrix=[]\n",
        "oof_preds2 = np.zeros((len(test)))\n",
        "kfold, scores = KFold(n_splits=splits,random_state=True), list()\n",
        "for train2, test2 in kfold.split(setused,targ):\n",
        "    x_train, x_test = setused.values[train2], setused.values[test2]\n",
        "    y_train, y_test = targ.values[train2], targ.values[test2]\n",
        "    model = cb2\n",
        "    model.fit(x_train, y_train)\n",
        "    preds = model.predict(x_test)\n",
        "    #############################\n",
        "    feature_importances = pd.DataFrame(model.feature_importances_,\n",
        "                                       index = setused.columns,\n",
        "                                        columns=['importance'])\n",
        "    sum=feature_importances.values\n",
        "    l.append(sum)\n",
        "    #############################\n",
        "    score = np.sqrt(mean_squared_error(y_test, preds))\n",
        "    scores.append(score)\n",
        "    print(score)\n",
        "    oof_preds2 += model.predict(test[setused.columns.tolist()].values)\n",
        "oof_preds2 = oof_preds2/splits\n",
        "\n",
        "print(\"Average: \", np.sum(scores)/len(scores))\n",
        "#3.5556950201910067"
      ],
      "execution_count": 21,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "3.476932683721444\n",
            "3.7224059807396492\n",
            "3.63754996192147\n",
            "3.4974337145071415\n",
            "3.652316499789447\n",
            "3.330023153304485\n",
            "3.8062989399707905\n",
            "3.7062989204833734\n",
            "3.9534274268919227\n",
            "3.7606651881127235\n",
            "3.9598905510490465\n",
            "3.5656502780118413\n",
            "3.8339717963560638\n",
            "3.778348980347873\n",
            "3.487104272737782\n",
            "3.807421071788855\n",
            "Average:  3.6859837137333695\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "f8kxobV4eKBt",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 340
        },
        "outputId": "9eb76464-7524-46f8-9bfd-d36c931ed827"
      },
      "source": [
        "train_set=setused\n",
        "labels=Y\n",
        "threshold=0.8\n",
        "add=0\n",
        "for item in l:\n",
        "  add+=item\n",
        "df_cv=pd.DataFrame(add/len(l),index=train_set.columns,columns=[\"importance\"]).sort_values('importance', ascending=False)\n",
        "imp_columns=df_cv[df_cv['importance']>threshold].index.tolist()\n",
        "df_cv=df_cv.reset_index()\n",
        "feat_imp = pd.Series(df_cv.importance.values, index=df_cv.drop([\"importance\"], axis=1)).sort_values(axis='index',ascending=False)\n",
        "X2=setused[imp_columns]\n",
        "feat_imp.nlargest(29).plot(kind='barh', figsize=(5,5))\n",
        "len(imp_columns)"
      ],
      "execution_count": 26,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "10"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 26
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<matplotlib.figure.Figure at 0x7f0932bb5198>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "JuStuCtkJPMN",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 17
        },
        "outputId": "3b288913-c264-4992-aaa7-5e702c6eff22"
      },
      "source": [
        "##submission module oof\n",
        "oof=oof_preds*.6+oof_preds2*.4\n",
        "filen='submission.xlsx'\n",
        "df_test2['tumor_size']=oof\n",
        "encode2 = dict(zip(df_test2.key, df_test2.tumor_size))\n",
        "df1=pd.DataFrame()\n",
        "df1['tumor_size']=df_test['tumor_size'].fillna(df_test['key'].map(encode2))\n",
        "df1=df1.clip(lower=0)\n",
        "df1.fillna(0,inplace=True)\n",
        "###change download adress here according to ur drive####################\n",
        "df1['tumor_size'].to_excel('/GD/My Drive/cancer/'+str(filen),index=False)\n",
        "files.download('/GD/My Drive/cancer/'+str(filen))\n",
        "#######################################################################"
      ],
      "execution_count": 25,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "\n",
              "    async function download(id, filename, size) {\n",
              "      if (!google.colab.kernel.accessAllowed) {\n",
              "        return;\n",
              "      }\n",
              "      const div = document.createElement('div');\n",
              "      const label = document.createElement('label');\n",
              "      label.textContent = `Downloading \"${filename}\": `;\n",
              "      div.appendChild(label);\n",
              "      const progress = document.createElement('progress');\n",
              "      progress.max = size;\n",
              "      div.appendChild(progress);\n",
              "      document.body.appendChild(div);\n",
              "\n",
              "      const buffers = [];\n",
              "      let downloaded = 0;\n",
              "\n",
              "      const channel = await google.colab.kernel.comms.open(id);\n",
              "      // Send a message to notify the kernel that we're ready.\n",
              "      channel.send({})\n",
              "\n",
              "      for await (const message of channel.messages) {\n",
              "        // Send a message to notify the kernel that we're ready.\n",
              "        channel.send({})\n",
              "        if (message.buffers) {\n",
              "          for (const buffer of message.buffers) {\n",
              "            buffers.push(buffer);\n",
              "            downloaded += buffer.byteLength;\n",
              "            progress.value = downloaded;\n",
              "          }\n",
              "        }\n",
              "      }\n",
              "      const blob = new Blob(buffers, {type: 'application/binary'});\n",
              "      const a = document.createElement('a');\n",
              "      a.href = window.URL.createObjectURL(blob);\n",
              "      a.download = filename;\n",
              "      div.appendChild(a);\n",
              "      a.click();\n",
              "      div.remove();\n",
              "    }\n",
              "  "
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "download(\"download_a27f70ed-212c-452e-adb4-7d9b93e23bbf\", \"submission.xlsx\", 588579)"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    }
  ]
}